package user

import (
	"context"
	stderrors "errors"

	"BookStack/pkg/errors"
)

// Service 定义用户服务接口
type Service interface {
	Register(ctx context.Context, username, email, password, nickname string) (*User, error)
	Authenticate(ctx context.Context, usernameOrEmail, password string) (*User, error)
	GetByID(ctx context.Context, id uint) (*User, error)
	UpdateProfile(ctx context.Context, id uint, nickname, avatar string) error
	ChangePassword(ctx context.Context, id uint, oldPassword, newPassword string) error
	ResetPassword(ctx context.Context, email string) error
	SetRole(ctx context.Context, id uint, role string) error
	SetStatus(ctx context.Context, id uint, status int) error
	GetUsers(ctx context.Context, page, pageSize int) ([]*User, int64, error)
	IsUsernameAvailable(ctx context.Context, username string) (bool, error)
	IsEmailAvailable(ctx context.Context, email string) (bool, error)
	DeleteUser(ctx context.Context, id uint) error
}

// userService 用户服务实现
type userService struct {
	repo Repository
}

// NewUserService 创建用户服务
func NewUserService(repo Repository) Service {
	return &userService{
		repo: repo,
	}
}

// Register 实现用户注册
func (s *userService) Register(ctx context.Context, username, email, password, nickname string) (*User, error) {
	// 检查用户名是否已存在
	exists, err := s.repo.ExistsByUsername(ctx, username)
	if err != nil {
		return nil, err
	}
	if exists {
		return nil, errors.New(errors.ErrCodeUsernameExists, "")
	}

	// 检查邮箱是否已存在
	exists, err = s.repo.ExistsByEmail(ctx, email)
	if err != nil {
		return nil, err
	}
	if exists {
		return nil, errors.New(errors.ErrCodeEmailExists, "")
	}

	// 创建用户
	user, err := NewUser(username, email, password, nickname)
	if err != nil {
		return nil, err
	}

	if err := s.repo.Create(ctx, user); err != nil {
		return nil, err
	}

	return user, nil
}

// Authenticate 实现通过用户名和密码验证用户
func (s *userService) Authenticate(ctx context.Context, usernameOrEmail, password string) (*User, error) {
	var user *User
	var err error

	// 尝试使用用户名查找
	user, err = s.repo.GetByUsername(ctx, usernameOrEmail)
	if err != nil {
		appErr := &errors.AppError{}
		if stderrors.As(err, &appErr) && appErr.Code == errors.ErrCodeUserNotFound {
			// 尝试使用邮箱查找
			user, err = s.repo.GetByEmail(ctx, usernameOrEmail)
			if err != nil {
				return nil, err
			}
		} else {
			return nil, err
		}
	}

	// 检查密码
	if !user.CheckPassword(password) {
		return nil, errors.New(errors.ErrCodeInvalidCredentials, "")
	}

	// 检查用户状态
	if !user.IsActive() {
		return nil, errors.New(errors.ErrCodeUserInactive, "")
	}

	return user, nil
}

// GetByID 实现获取用户信息
func (s *userService) GetByID(ctx context.Context, id uint) (*User, error) {
	return s.repo.GetByID(ctx, id)
}

// UpdateProfile 实现更新用户信息
func (s *userService) UpdateProfile(ctx context.Context, id uint, nickname, avatar string) error {
	user, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return err
	}

	user.UpdateProfile(nickname, avatar)
	return s.repo.Update(ctx, user)
}

// ChangePassword 实现修改密码
func (s *userService) ChangePassword(ctx context.Context, id uint, oldPassword, newPassword string) error {
	user, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return err
	}

	// 检查旧密码
	if !user.CheckPassword(oldPassword) {
		return errors.New(errors.ErrCodeInvalidCredentials, "")
	}

	// 修改密码
	if err := user.ChangePassword(newPassword); err != nil {
		return err
	}

	return s.repo.Update(ctx, user)
}

// ResetPassword 实现重置密码
func (s *userService) ResetPassword(ctx context.Context, email string) error {
	// TODO: 实现重置密码功能
	return nil
}

// SetRole 实现设置用户角色
func (s *userService) SetRole(ctx context.Context, id uint, role string) error {
	user, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return err
	}

	if err := user.SetRole(role); err != nil {
		return err
	}

	return s.repo.Update(ctx, user)
}

// SetStatus 实现启用/禁用用户
func (s *userService) SetStatus(ctx context.Context, id uint, status int) error {
	user, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return err
	}

	if err := user.SetStatus(status); err != nil {
		return err
	}

	return s.repo.Update(ctx, user)
}

// GetUsers 实现获取用户列表
func (s *userService) GetUsers(ctx context.Context, page, pageSize int) ([]*User, int64, error) {
	offset := (page - 1) * pageSize
	return s.repo.List(ctx, offset, pageSize)
}

// IsUsernameAvailable 实现检查用户名是否可用
func (s *userService) IsUsernameAvailable(ctx context.Context, username string) (bool, error) {
	exists, err := s.repo.ExistsByUsername(ctx, username)
	if err != nil {
		return false, err
	}
	return !exists, nil
}

// IsEmailAvailable 实现检查邮箱是否可用
func (s *userService) IsEmailAvailable(ctx context.Context, email string) (bool, error) {
	exists, err := s.repo.ExistsByEmail(ctx, email)
	if err != nil {
		return false, err
	}
	return !exists, nil
}

// DeleteUser 实现删除用户
func (s *userService) DeleteUser(ctx context.Context, id uint) error {
	return s.repo.Delete(ctx, id)
}
